﻿using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Text;
using System.Configuration;
using System.ComponentModel;

namespace LibSnesDotNet
{
	public class ObservableConfigurationElement : ConfigurationElement, INotifyPropertyChanged
	{
		public event PropertyChangedEventHandler PropertyChanged;

		public new object this[string key]
		{
			get { return base[key]; }
			set
			{
				base[key] = value;

				if (PropertyChanged != null)
				{
					key = char.ToUpper(key[0]) + key.Substring(1);
					PropertyChanged(this, new PropertyChangedEventArgs(key));
				}
			}
		}
	}

	public class ObservableConfigurationSection : ConfigurationSection, INotifyPropertyChanged
	{
		public event PropertyChangedEventHandler PropertyChanged;

		public new object this[string key]
		{
			get { return base[key]; }
			set
			{
				base[key] = value;

				if (PropertyChanged != null)
				{
					key = char.ToUpper(key[0]) + key.Substring(1);
					PropertyChanged(this, new PropertyChangedEventArgs(key));
				}
			}
		}
	}

	public abstract class ObservableConfigurationElementCollection : ConfigurationElementCollection, INotifyCollectionChanged, INotifyPropertyChanged
	{
		public event NotifyCollectionChangedEventHandler CollectionChanged;
		public event PropertyChangedEventHandler PropertyChanged;

		public new void BaseAdd(ConfigurationElement element)
		{
			base.BaseAdd(element);

			if (CollectionChanged != null)
			{
				CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, element));
			}

			if (PropertyChanged != null)
			{
				PropertyChanged(this, new PropertyChangedEventArgs("Count"));
			}
		}

		public new void BaseAdd(ConfigurationElement element, bool throwIfExists)
		{
			base.BaseAdd(element, throwIfExists);

			if (CollectionChanged != null)
			{
				CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, element));
			}

			if (PropertyChanged != null)
			{
				PropertyChanged(this, new PropertyChangedEventArgs("Count"));
			}
		}

		public new void BaseAdd(int index, ConfigurationElement element)
		{
			base.BaseAdd(index, element);

			if (CollectionChanged != null)
			{
				CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, element, index));
			}

			if (PropertyChanged != null)
			{
				PropertyChanged(this, new PropertyChangedEventArgs("Count"));
			}
		}

		public new void BaseRemove(object key)
		{
			ConfigurationElement element = base.BaseGet(key);
			int index = BaseIndexOf(element);
			base.BaseRemove(key);

			if (CollectionChanged != null)
			{
				CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, element, index));
			}

			if (PropertyChanged != null)
			{
				PropertyChanged(this, new PropertyChangedEventArgs("Count"));
			}
		}

		public new void BaseRemoveAt(int index)
		{
			ConfigurationElement element = BaseGet(index);
			base.BaseRemoveAt(index);

			if (CollectionChanged != null)
			{
				CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, element, index));
			}

			if (PropertyChanged != null)
			{
				PropertyChanged(this, new PropertyChangedEventArgs("Count"));
			}
		}

		public new void BaseClear()
		{
			base.BaseClear();

			if (CollectionChanged != null)
			{
				CollectionChanged(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
			}

			if (PropertyChanged != null)
			{
				PropertyChanged(this, new PropertyChangedEventArgs("Count"));
			}
		}
	}
}
